package com.easyadmin.service.impl;

import com.easyadmin.entity.constants.Constants;
import com.easyadmin.entity.dto.SessionUserDto;
import com.easyadmin.entity.enums.*;
import com.easyadmin.entity.po.SysAccount;
import com.easyadmin.entity.po.SysMenu;
import com.easyadmin.entity.query.SysAccountQuery;
import com.easyadmin.entity.vo.PaginationResult;
import com.easyadmin.entity.vo.SimplePage;
import com.easyadmin.exception.BusinessException;
import com.easyadmin.mappers.SysAccountMapper;
import com.easyadmin.service.SysAccountService;
import com.easyadmin.service.SysMenuService;
import com.easyadmin.utils.StringTools;
import com.easyadmin.utils.VerifyUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * 账号信息 业务接口实现
 */
@Service("sysAccountService")
public class SysAccountServiceImpl implements SysAccountService {

    @Resource
    private SysAccountMapper<SysAccount, SysAccountQuery> sysAccountMapper;

    @Resource
    private SysMenuService sysMenuService;

    /**
     * 根据条件查询列表
     */
    @Override
    public List<SysAccount> findListByParam(SysAccountQuery param) {
        return this.sysAccountMapper.selectList(param);
    }

    /**
     * 根据条件查询列表
     */
    @Override
    public Integer findCountByParam(SysAccountQuery param) {
        return this.sysAccountMapper.selectCount(param);
    }

    /**
     * 分页查询方法
     */
    @Override
    public PaginationResult<SysAccount> findListByPage(SysAccountQuery param) {
        int count = this.sysAccountMapper.selectCount(param);
        int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();
        int pageNo = 0;
        if (null != param.getPageNo()) {
            pageNo = param.getPageNo();
        }
        SimplePage page = new SimplePage(pageNo, count, pageSize);
        param.setSimplePage(page);
        List<SysAccount> list = this.sysAccountMapper.selectList(param);
        PaginationResult<SysAccount> result = new PaginationResult<>(count, pageSize, pageNo, page.getPageTotal(), list);
        return result;
    }

    /**
     * 新增
     */
    @Override
    public Integer add(SysAccount bean) throws BusinessException {
        try {
            return this.sysAccountMapper.insert(bean);
        } catch (DuplicateKeyException e) {
            throw new BusinessException("信息已经存在");
        }
    }

    /**
     * 批量新增
     */
    @Override
    public Integer addBatch(List<SysAccount> listBean) {
        if (listBean == null || listBean.isEmpty()) {
            return 0;
        }
        return this.sysAccountMapper.insertBatch(listBean);
    }

    /**
     * 批量新增或者修改
     */
    @Override
    public Integer addOrUpdateBatch(List<SysAccount> listBean) {
        if (listBean == null || listBean.isEmpty()) {
            return 0;
        }
        return this.sysAccountMapper.insertOrUpdateBatch(listBean);
    }

    /**
     * 根据Phone修改
     */
    @Override
    public Integer updateByPhone(SysAccount bean, String phone) {
        return this.sysAccountMapper.updateByPhone(bean, phone);
    }


    /**
     * 根据Phone删除
     */
    @Override
    public Integer deleteByPhone(String phone) {
        return this.sysAccountMapper.deleteByPhone(phone);
    }


    /**
     * 根据Phone获取对象
     */
    @Override
    public SysAccount getSysAccountByPhone(String phone) {
        return this.sysAccountMapper.selectByPhone(phone);
    }


    /**
     * 根据UserId修改
     */
    @Override
    public Integer updateByUserId(SysAccount bean, Integer userId) {
        return this.sysAccountMapper.updateByUserId(bean, userId);
    }


    /**
     * 根据UserId删除
     */
    @Override
    public Integer deleteByUserId(Integer userId) {
        return this.sysAccountMapper.deleteByUserId(userId);
    }


    /**
     * 根据UserId获取对象
     */
    @Override
    public SysAccount getSysAccountByUserId(Integer userId) {
        return this.sysAccountMapper.selectByUserId(userId);
    }


    /**
     * 根据Account修改
     */
    @Override
    public Integer updateByAccount(SysAccount bean, String account) {
        return this.sysAccountMapper.updateByAccount(bean, account);
    }


    /**
     * 根据Account删除
     */
    @Override
    public Integer deleteByAccount(String account) {
        return this.sysAccountMapper.deleteByAccount(account);
    }


    /**
     * 根据Account获取对象
     */
    @Override
    public SysAccount getSysAccountByAccount(String account) {
        return this.sysAccountMapper.selectByAccount(account);
    }

    @Override
    public void saveSysAccount(SysAccount sysAccount) throws BusinessException {
        SysAccount accountDb = sysAccountMapper.selectByAccount(sysAccount.getAccount());
        SysAccount phoneDb = sysAccountMapper.selectByPhone(sysAccount.getPhone());

        if (sysAccount.getUserId() == null) {
            if (accountDb != null) {
                throw new BusinessException(String.format("账号【%s】已经存在", sysAccount.getAccount()));
            }

            if (phoneDb != null) {
                throw new BusinessException(String.format("手机号【%s】已经存在", sysAccount.getPhone()));
            }
            sysAccount.setCreateTime(new Date());
            sysAccount.setStatus(UserStatusEnum.ENABLE.getStatus());
            sysAccount.setPassword(StringTools.encodeByMD5(sysAccount.getPassword()));
            this.sysAccountMapper.insert(sysAccount);

        } else {
            sysAccount.setPassword(null);
            sysAccount.setStatus(null);
            sysAccount.setUserType(null);
            if (accountDb != null && !accountDb.getUserId().equals(sysAccount.getUserId())) {
                throw new BusinessException(String.format("账号【%s】已经存在", sysAccount.getAccount()));
            }

            if (phoneDb != null && !phoneDb.getUserId().equals(sysAccount.getUserId())) {
                throw new BusinessException(String.format("手机号【%s】已经存在", sysAccount.getPhone()));
            }

            this.sysAccountMapper.updateByUserId(sysAccount, sysAccount.getUserId());
        }
    }

    @Override
    public void updatePassword(Integer userId, String oldPassword, String password) throws BusinessException {
        SysAccount dbAccount = this.sysAccountMapper.selectByUserId(userId);
        if (dbAccount == null) {
            throw new BusinessException("账号不存在");
        }
        SysAccount sysAccount = new SysAccount();
        if (!StringTools.isEmpty(oldPassword) && !StringTools.encodeByMD5(oldPassword).equals(dbAccount.getPassword())) {
            throw new BusinessException("旧密码不正确");
        }
        sysAccount.setPassword(StringTools.encodeByMD5(password));
        this.sysAccountMapper.updateByUserId(sysAccount, userId);
    }

    @Override
    public SessionUserDto login(String account, String password, Boolean haveMd5) throws BusinessException {
        if (StringTools.isEmpty(account) || StringTools.isEmpty(password)) {
            throw new BusinessException("账号，密码不能为空");
        }

        SysAccount sysAccount = null;
        if (VerifyUtils.verify(VerifyRegexEnum.POSITIVE_INTEGER, account)) {
            sysAccount = this.sysAccountMapper.selectByPhone(account);
        } else {
            sysAccount = this.sysAccountMapper.selectByAccount(account);
        }

        if (sysAccount != null && !AccountStatusEnum.ENABLE.getStatus().equals(sysAccount.getStatus())) {
            throw new BusinessException("账号已禁用");
        }

        password = haveMd5 ? password : StringTools.encodeByMD5(password);
        if (null == sysAccount || !sysAccount.getPassword().equals(password)) {
            throw new BusinessException("账号密码错误");
        }

        SessionUserDto sessionUserDto = new SessionUserDto();
        sessionUserDto.setUserId(sysAccount.getUserId());
        sessionUserDto.setUserName(sysAccount.getUserName());

        List<SysMenu> allMenus = sysMenuService.selectAllMenuByRoleIds(sysAccount.getRoles());

        List<SysMenu> menuList = new ArrayList<>();
        List<String> permissionCodeList = new ArrayList<>();


        sessionUserDto.setPermissionCodeList(permissionCodeList);

        for (SysMenu sysMenu : allMenus) {
            if (MenuTypeEnum.MEMU.getType().equals(sysMenu.getMenuType())) {
                menuList.add(sysMenu);
            }
            permissionCodeList.add(sysMenu.getPermissionCode());
        }

        sessionUserDto.setMenuList(sysMenuService.convertLine2Tree4Menu(menuList, Constants.DEFAULT_ROOT_MENUID, false));
        return sessionUserDto;
    }

    @Override
    public SessionUserDto autoLogin(Cookie[] cookies) {
        try {

            if (null == cookies || cookies.length == 0) {
                return null;
            }

            String cookeInfo = null;
            for (Cookie cookie : cookies) {
                if (Constants.COOKIE_KEY.equals(cookie.getName())) {
                    cookeInfo = cookie.getValue();
                    break;
                }
            }
            if (StringTools.isEmpty(cookeInfo)) {
                return null;
            }
            String[] cookeInfoArray = cookeInfo.split("\\|");
            if (cookeInfoArray.length != Constants.LENGTH_2) {
                return null;
            }
            return login(cookeInfoArray[0], cookeInfoArray[1], true);
        } catch (Exception e) {
            return null;
        }
    }
}